<?php
//-------------------------------------------------------------------------------------------------------
    require_once($config['app_dir'] . '/includes/object.class.php');
    require_once($config['app_dir'] . '/includes/db.class.php');
    require_once($config['app_dir'] . '/includes/date.class.php');
    require_once($config['app_dir'] . '/includes/number.class.php');
    //---------------------------------------------------------------------------------------------------
    // prev
    /*
     class objPointTimePrice {
            protected $time = false;
            protected $price = false;
            public $new_time = false;
            public $new_price = false;

            protected $flag_translated = false;

        public function __construct($aTime, $aPrice) {
            $this->time = $aTime;
            $this->price = $aPrice;
            $this->new_time = $aTime;
            $this->new_price = $aPrice;
        } //constructor

        public function __set($aName, $aValue) {
            $aName = strtolower($aName);
            switch( $aName ) {
                case 'time' :
                    $this->time = $aValue;
                    $this->new_time = $aValue;
                    $this->flag_translated = false;
                break;
                //------------------------------------------------------------------------------------------
                case 'price' :
                    $this->price = $aValue;
                    $this->new_price = $aValue;
                    $this->flag_translated = false;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_time' :
                    $this->new_time = $aValue;
                    $this->flag_translated = true;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_price' :
                    $this->new_price = $aValue;
                    $this->flag_translated = true;
                break;
            }//switch
        } //setter

        public function __get($aName) {
            $aName = strtolower($aName);
            switch( $aName ) {
                case 'time' :
                    return $this->time;
                break;
                //------------------------------------------------------------------------------------------
                case 'price' :
                    return $this->price;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_time' :
                    return $this->new_time ;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_price' :
                    return $this->new_price;
                break;
            }//switch
        } //getter


    } //class PointTimePrice
    //-------------------------------------------------------------------------------------------------------
    class objStopMarkItem extends objPointTimePrice {
            public $color = false;

        public function __construct($aTime, $aPrice, $aPrice) {
            parent::__construct($aTime, $aPrice);
            $this->color = $aColor;
        } //constructor

    } //class objStopMarkItem
    //-------------------------------------------------------------------------------------------------------
    class objDataItem {
            public $id = false;

        public function __construct($aID) {
            $this->id = $aID;
        }//constructor

    }//class DataItem
    //-------------------------------------------------------------------------------------------------------
    class objSystemItem extends objDataItem {
            public $name = false;

        public function __construct($aID, $aName = false) {
            parent::__construct($aID);
            $this->name = $aName;
        } //constructor

    } //class  SystemItem
    //-------------------------------------------------------------------------------------------------------
    class objRateItem  extends objDataItem {
            public $id = false;
            public $pair = false;
            public $unitime = false;
            public $time = false;
            public $direction = false;
            public $ask = false;
            public $bid = false;

    } //class RateItem
    //-------------------------------------------------------------------------------------------------------
    class objForecastItem  extends objDataItem {

            public $Begin = false;
            public $End = false;
            public $Close = false;
            public $Stop = false;
            public $Last = false;

            public $System = false;
            public $Rate = false;

            public $active = false;
            public $visible = false;
            public $color = false;
            public $pip = false;
            public $side = false;
            public $pair = false;

        public function isActive() {
            return 3==$this->color;
        } //isActive

    } //class ForecastItem
    //-------------------------------------------------------------------------------------------------------
    class objQuoteItem  extends objDataItem {
            public $time = false;
            public $time_t = false;
            public $high = false;
            public $low = false;
            public $open = false;
            public $close = false;

    } //class QuoteItem
    //-------------------------------------------------------------------------------------------------------
    class objDataList {
            protected $_index = array();
            protected $_data = array();


        protected function ClearIndex() {
            unset($this->_index);
            $this->_index = array();
        } //ClearIndex

        protected function ClearData() {
            unset($this->_data);
            $this->_data = array();
        } //ClearData

        protected function RebuildIndex() {
            $this->ClearIndex();
            foreach($this->_data as $aKey => $aValue) {
                $this->_index[] = $aKey;
            } //foreach

        } //rebuildIndex

        public function clear() {
            $this->ClearData();
            $this->ClearIndex();
        } //clear

        public function add(objDataItem $aItem) {
            $this->_data[$aItem->id] = $aItem;
            $this->_index[] = $aItem->id;
        } //add

        public function remove($aID) {
            unset($this->_data[$aID]);
            $this->RebuildIndex();
        } //remove

        public function find($aID) {
            if( in_array($aID, $this->_index) )
                foreach($this->_data as $key => $val )
                    if( $aID == $key ) {
                        return $val;
                    } // if + foreach
            return false;
        } //find

        public function isEmpty() {
            return !is_array($this->_data) || count($this->_data)==0;
        } //isEmpty

        public function length() {
            return count($his->_data);
        } //length

    } //class DataList
    //-------------------------------------------------------------------------------------------------------
    class objForecastDataList extends objDataList {

        public function add(objForecastItem $aItem) {
            parent::add($aItem);
        } //add

        public function GetLast() {
            for( $i=$this->length()-1; $i>-1; $i-- ) {
                $aItem = $this->find($this->_index[$i]);
                if( $aItem->isActive() ) return $aItem;
            } //for

            return false;
        } //GetLast

    } // class ForecastDataList
    //-------------------------------------------------------------------------------------------------------
    class StockManipulaion {

        static public  function isWeekendDay($timestamp) {
            return  0 == intval(DateConvert::Date('w', $timestamp)) ||
                    6 == intval(DateConvert::Date('w', $timestamp)) ;
        }//isWeekendDay

        static public function inInteraval($x, $Xmin, $Xmax, $left=true, $right=false) {
            $result = true;

            if( true==$left ) $result = $result && ($Xmin <= $x);
                else $result = $result && ($Xmin < $x);

            if( true==$right ) $result = $result && ($x <= $Xmax);
                else $result = $result && ($x < $Xmax);

            return $result;
        }//inInteraval

    } //StockManipulation
    //-------------------------------------------------------------------------------------------------------
    class objStockData  extends objObject implements iErrorHandler {
            protected $id = false;
            protected $system_id = false;
            protected $_trade = false;
            protected $_scale = false;
            protected $_start = false;
            protected $_finish = false;
            protected $_t = false;
            protected $_db = false;

            public $QuoteList = false;
            public $ForecastList = false;
            public $StopMarkList = false;
            public $StopList = false;

            protected $_sql_querys = array();

            protected $_error_str = array('no error',//0
                                          'Input parameters are empty',//1
                                          'Data for selected parameters are empty',//2
                                          'Minimal interval beetween xvaluee is 0',//3
                                          'Translation vectors error',//4
                                          'Chosing vectors error - no data',//5
                                          "Can't translate stop marks"//6
                                         );

        public function __construct($aTrade, $aStart, $aFinish, $t=false, $aSystem=false) {
            $this->_trade = $aTrade;
            $this->_start = $aStart;
            $this->_finish = $aFinish;
            $this->_t = $t;

            if (!$this->_trade || !$this->_start || !$this->_finish) throw new Exception($this->Error(1));

            $this->_db = objDataBase::GetInstance();
            $this->system_id = $aSystem;

            $this->_sqls();

            $this->QuoteList = new objDataList();
            $this->ForecastList = new objForecastDataList();
            $this->StopMarkList = new objDataList();
        } //constructor

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function Dump() {

        } //Dump

        public function GenID() {
            return $this->id =  md5(strval($this->_trade) .
                                strval($this->_start) .
                                strval($this->_finish) .
                                strval($this->_t) .
                                intval($this->system_id));
        } //GenID

        public function GetID() {
            return $this->id;
        } //GetID

        public function SetSystemID( $aValue ){
            $this->system_id = $aValue;
            $this->_sqls();
        }//SetSystemID

        public function __set($aName, $aValue) {
            $aName = strtolower($aName);
            switch( $aName ) {
                case 'system' :
                    $this->SetSystemID($aValue);
                break;
                //----------------------------------------------------
            } //switch
        } //setter

        public function __get($aName) {
            $aName = strtolower($aName);
            switch( $aName ) {
                case 'system' :
                    return $this->system_id;
                break;
                //----------------------------------------------------
                case 'id' :
                    if( !$this->id ) $this->GenID();
                    return $this->id;
                break;
            } //switch
        } //getter

        protected function _sqls() {
            $this->_sql_querys['quotes'] =
            "SELECT ".
                "t.Pair, ".
                "t.TradeID, ".
                "q.TimeStart, ".
                "q.Time_T, ".
                "from_unixtime(q.`TimeStart`,'%Y')as DateYear, ".
                "q.O, ".
                "q.H, ".
                "q.L, ".
                "q.C ".
            "FROM ".
                "fa_quotes q ".
                "LEFT OUTER JOIN fa_trades t ON (q.TradeID = t.TradeID) ".
            "WHERE t.TradeId=$this->_trade ".
                        " AND q.TimeStart between '$this->_start' and '$this->_finish' ".
            "ORDER BY ".
                "t.TradeID, ".
                "q.TimeStart ";
            //------------------------------------------------------------------
            $where_systemid = '';
            if( $this->system_id ) $where_systemid = ' AND f.SystemID = ' . $this->system_id. ' ';
            //------------------------------------------------------------------
            $this->_sql_querys['forecast_main'] =
            "SELECT f.ForecastID, f.BeginPrice, f.BeginTime,f.EndPrice,t.TradeID,t.Pair, f.Color, f.Side,  " .
                " f.StopPrice, ".
                " f.CloseTime is null AS flagActive, ".
                " (f.EndTime is Null ) AS flagEndTime, ".
                " (f.EndPrice is Null ) AS flagEndPrice, ".
                " (f.StopPrice is Null ) AS flagStopPrice, ".

                " lq.LastCloseTime as LastTime, " .
                " lq.LastPrice as LastPrice, ".

                " COALESCE(f.CloseTime,lq.LastCloseTime) as CloseTime,   ".
                " COALESCE(f.ClosePrice,lq.LastClosePrice) as ClosePrice,   ".
                " COALESCE(f.EndTime, f.CloseTime, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT)) as EndTime, ".

                " round((1 - 2 * f.Side) * (COALESCE(f.ClosePrice, lq.LastClosePrice) - f.BeginPrice) / t.PipSize) as Pip, ".

                " COALESCE(round( (1 - 2 * f.Side) * (f.StopPrice - f.BeginPrice) / t.PipSize ), 0) as StopPip, ".
                " COALESCE(round( (1 - 2 * f.Side) * (f.EndPrice - f.BeginPrice) / t.PipSize ), 0) as EndPip, ".
                " COALESCE(round( (1 - 2 * f.Side) * (f.ClosePrice - f.BeginPrice) / t.PipSize ), 0) as ClosePip, ".

                " r.Ask, ".
                " r.Bid, ".
                " r.Time as RateTimeUnix, ".
                " r.Direction, ".
                " r.RateTime, ".
                " s.`Name` as `SystemName`, ".
                " s.SystemID " .
            "FROM vfa_forecast f ".
                   " LEFT OUTER JOIN fa_trades t ON (f.TradeID = t.TradeID) ".
                   " LEFT OUTER JOIN fa_systems s ON (f.SystemID = s.SystemID) ".
                   " LEFT OUTER JOIN  ".
                        " (SELECT *, FROM_UNIXTIME(tr.`Time`, '%Y-%m-%d %H:%i:%s') as RateTime FROM fa_rates tr ORDER BY tr.SortIndex LIMIT 1) r ".
                        " ON (f.TradeID=r.TradeID) ".

                   " LEFT OUTER JOIN " .
                    " ( " .
                     " SELECT " .
                          " ttq.TradeID, " .
                          " ttq.C as LastClosePrice, " .
                          " GREATEST(ttq.O, ttq.C, ttq.H, ttq.L) as LastPrice, ".
                          " ttq.TimeStart as LastCloseTime, " .
                          " ttq.Time_T as LastCloseTimeT ".
                     " FROM fa_quotes ttq " .
                         " RIGHT OUTER JOIN ( " .
                               " SELECT tq.TradeID, max(tq.TimeStart) as max_quote_time " .
                               " FROM fa_quotes tq " .
                               " GROUP BY tq.TradeID) qq " .
                               " ON (qq.max_quote_time=ttq.TimeStart and qq.TradeID=ttq.TradeID) " .
                    ") lq " .
                    "ON (f.TradeID = lq.TradeID) " .
                    "WHERE (1=1)";

            //------------------------------------------------------------------
            $this->_sql_querys['forecast_soft'] =
                $this->_sql_querys['forecast_main'] .
                " AND t.TradeID=$this->_trade AND f.BeginTime between '$this->_start' and '$this->_finish'" . $where_systemid .
                " ORDER BY COALESCE(f.EndTime, f.CloseTime, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT))";

            //------------------------------------------------------------------
            $this->_sql_querys['forecast_strong'] =
                $this->_sql_querys['forecast_main'] .
                "AND t.TradeID=$this->_trade ".
                  " AND f.BeginTime between '$this->_start' and '$this->_finish'".
            	  " AND COALESCE(f.EndTime, f.CloseTime, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT)) between '$this->_start' and '$this->_finish' " .
                  $where_systemid .
             " ORDER BY COALESCE(f.EndTime, f.CloseTime, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT))";
            //------------------------------------------------------------------
            $this->_sql_querys['rate'] =
                           "SELECT *, FROM_UNIXTIME(r.`Time`, '%Y-%m-%d %H:%i:%s') as RateTime FROM fa_rates r WHERE r.TradeID=? ORDER BY r.SortIndex";

        } //sqls

    } //class StockData

    */
    // /prev

    //---------------------------------------------------------------------------------------------------

        class objPointTimePrice {
            protected $time = false;
            protected $price = false;
            public $new_time = false;
            public $new_price = false;

            protected $flag_translated = false;

        public function __construct($aTime, $aPrice) {
            $this->time = $aTime;
            $this->price = $aPrice;
            $this->new_time = $aTime;
            $this->new_price = $aPrice;
        } //constructor

        public function __set($aName, $aValue) {
            $aName = strtolower($aName);
            switch( $aName ) {
                case 'time' :
                    $this->time = $aValue;
                    $this->new_time = $aValue;
                    $this->flag_translated = false;
                break;
                //------------------------------------------------------------------------------------------
                case 'price' :
                    $this->price = $aValue;
                    $this->new_price = $aValue;
                    $this->flag_translated = false;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_time' :
                    $this->new_time = $aValue;
                    $this->flag_translated = true;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_price' :
                    $this->new_price = $aValue;
                    $this->flag_translated = true;
                break;
            }//switch
        } //setter

        public function __get($aName) {
            $aName = strtolower($aName);
            switch( $aName ) {
                case 'time' :
                    return $this->time;
                break;
                //------------------------------------------------------------------------------------------
                case 'price' :
                    return $this->price;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_time' :
                    return $this->new_time ;
                break;
                //------------------------------------------------------------------------------------------
                case 'new_price' :
                    return $this->new_price;
                break;
            }//switch
        } //getter


    } //class PointTimePrice
    //-------------------------------------------------------------------------------------------------------
    abstract class objAbstractDataItem extends objObject {
            public $id = false;

        public function __construct($aID) {
            $this->id = $aID;
        }//constructor

        abstract function Import($Arr);
        abstract function Export();
    }//class objAbstractDataItem
    //--------------------------------------------------------------------------------------------------
    abstract class objAbstractDataItems {
            protected $flag_prepared = false;
            protected $_data = false;
            protected $items = array();
            protected $_sql_querys = array();

            protected $_id = false;
            protected $_system = false;
            protected $_trade = false;
            protected $_start = false;
            protected $_finish = false;

        public function __construct($aID=false) {
            if( $aID ) {
                $this->_id = intval($aID);

                //$this->_sqls();
            }
        }//constructor

        public function ClassName() {
            return  __CLASS__;
        }//ClassName


        public function __set($aName, $aValue) {
            $aName = strtolower($aName);
            switch( $aName ) {
                case 'system':
                    $this->_system = intval($aValue);
                    //$this->_sqls();
                break;
                //-------------------------------------------------------------
                case 'id':
                    $this->_id = intval($aValue);
                    //$this->_sqls();
                break;
                //-------------------------------------------------------------
                case 'trade':
                    $this->_trade = intval($aValue);
                    //$this->_sqls();
                break;
                //-------------------------------------------------------------
                case 'start':
                    $this->_start = intval( is_int($aValue) ? $aValue : DateConvert::Date2('U', $aValue));

                    //$this->_sqls();
                break;
                //-------------------------------------------------------------
                case 'finish':
                    $this->_finish = intval( is_int($aValue) ? $aValue : DateConvert::Date2('U', $aValue));

                    //$this->_sqls();
                break;
            }//switch
        } //setter

        public function __get($aName) {
            if( $this->_id && array_key_exists($aName, $this->_data) ) return $this->_data[$aName];

            $aName = strtolower($aName);
            switch( $aName ) {
                case 'system':
                    return $this->_system;
                break;
                //-------------------------------------------------------------
                case 'id':
                    return $this->_id;
                break;
                //-------------------------------------------------------------
                case 'trade':
                    return $this->_trade;
                break;
                //-------------------------------------------------------------
                case 'start':
                    return $this->_start;
                break;
                //-------------------------------------------------------------
                case 'finish':
                    return $this->_finish;
                break;
                //-------------------------------------------------------------
                case 'start_ymd':
                    return ($this->_start ? DateConvert::Date('Y-m-d H:i:s', $this->_start) : false);
                break;
                //-------------------------------------------------------------
                case 'finish_ymd':
                    return ( $this->_finish ? DateConvert::Date('Y-m-d H:i:s', $this->_finish) : false);
                break;
            }//switch

        } //getter

        abstract public function isParamValid();

        public function isEmpty() {
            return empty($this->_data) || !$this->_data;
        }//isEmpty

        public function Load($force=false) {
            if( !$force && $this->flag_prepared ) return $this->_data;

            if( $this->isParamValid() ) return false;

            $this->_sqls();

            if( $this->_id )
                $this->_data = objDataBase::GetInstance()->handler->GetRow($this->_sql_querys['items']);
            else
                $this->_data = objDataBase::GetInstance()->handler->GetAll($this->_sql_querys['items']);
            $this->flag_prepared = true;
            return  $this->_data;
        } //Load

        public function Reload() {
            $this->Load($force = true);
        } //Reload

        public function Clean() {
            unset($this->_data);
            $this->_data = array();
        } //Clean

        public function Count() {
            return count($this->_data);
        } //count

        public function GetArr($aIndex=false) {
            if( !$this->flag_prepared ) $this->Load();
            if( is_int($aIndex) && $aIndex>-1 && $aIndex<count($this->_data) )
                return $this->_data[$aIndex];
            else
                return $this->_data;
        }//getArr

        abstract protected function CreateItem($aData);

        public function AddItem(objQuoteDataItem $aItem) {
            $this->items[] = $aItem;
        } //AddItem

        public function GetItem($aIndex) {
            if( array_key_exists($aIndex, $this->items) ) return $this->items[$aIndex];
            else return false;
        } //getItem

        public function DelItem($aIndex) {
            if( array_key_exists($aIndex, $this->items) ) unset($this->items[$aIndex]);
        } //DelItem

        public function Build() {
            $this->items = array();
            for($i=0; $i<count($this->_data); $i++) {
                $this->AddItem($this->CreateItem($this->_data[$i]));
            }
            return $this->items;
        } //Build

        public function Export() {
            $result = array();
            for($i=0; $i<$this->Count(); $i++) {
                $result[] = $this->data[$i]->Export();
            }//for
            return $result;
        } //Export

        abstract protected function BuildWhere();

        abstract protected function  _sqls();

    }// class AbstractDataItems
    //--------------------------------------------------------------------------------------------------
    class objQuoteDataItem  extends objAbstractDataItem {
            public $time = false;
            public $trade = false;
            public $time_t = false;
            public $high = false;
            public $low = false;
            public $open = false;
            public $close = false;

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function Import($Arr) {
            $this->id = intval($Arr['QuoteID']);
            $this->trade = intval($Arr['TradeID']);
            $this->time = intval($Arr['TimeStart']);
            $this->time_t = intval($Arr['Time_T']);
            $this->high = floatval($Arr['H']);
            $this->low = floatval($Arr['L']);
            $this->close = floatval($Arr['C']);
            $this->open = floatval($Arr['O']);
        }//Import

        public function Export() {
            $result = array();
            $result['id'] = $this->id;
            $result['time'] = $this->time;
            $result['time_t'] = $this->time_t;
            $result['start'] = $this->time;
            $result['open'] = $this->open;
            $result['close'] = $time->close;
            $result['low'] = $time->low;
            $result['high'] = $time->high;
            return $result;
        } //export

        public function getMaxValue() {
            return max($this->high,  $this->low, $this->close, $this->open);
        } //getMaxValue

    } //class QuoteDataItem

    //---------------------------------------------------------------------------------------------------
    class objForecastDataItem  extends objAbstractDataItem {

            public $Begin = false;
            public $End = false;
            public $Close = false;
            public $Stop = false;
            public $Last = false;

            public $System = false;
            public $Rate = false;

            public $active = false;
            public $visible = false;
            public $color = false;
            public $pip = false;
            public $side = false;
            public $pair = false;

        public function __construct() {
            $this->Begin = new objPointTimePrice();
            $this->End = new objPointTimePrice();
            $this->Close = new objPointTimePrice();
            $this->Stop = new objPointTimePrice();
            $this->Last = new objPointTimePrice();
        } //constructor

        public function isActive() {
            return 3==$this->color;
        } //isActive

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function Import($Arr) {
        }//Import

        public function Export() {
            $result = array();
            $result['begin']['time'] = $this->Begin->time;
            $result['begin']['price'] = $this->Begin->price;
            $this->Begin->price;
            return $result;
        } //export

    } //class ForecastDataItem
    //---------------------------------------------------------------------------------------------------
    class objQuoteDataItems extends objAbstractDataItems {

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function isParamValid() {
            return !($this->_id || ( $this->_trade && ( $this->_start || $this->_finish ) ));
        }//isParamValid

        public function TimeDelta() {
            $min = 0;
            for($i=0; $i<count($this->_data)-1; $i++)
                $min = min( $min, abs($this->_data[$i]['TimeStart'] - $this->_data[$i+1]['TimeStart']) );
            return $min;
        } //TimeDelta

        public function getMinTime() {
            $result = $this->_data[0]['TimeStart'];
            for($i=0; $i<count($this->_data); $i++)
                $result = min( $min, $this->_data[$i]['TimeStart'] );
            return $result;
        } //getMinTime

        public function getMaxTime() {
            $result = -1;
            for($i=0; $i<count($this->_data); $i++)
                $result = max( $min, $this->_data[$i]['TimeStart'] );
            return $result;
        } //getMinTime
        //-------------------------------------------------------------------------------
        protected function CreateItem($aData) {
            $Item = new objQuoteDataItem();
            $Item->Import($aData);
            return $Item;
        } //CreateItem
        //-------------------------------------------------------------------------------
        protected function _sqls() {
            $this->_sql_querys['items'] =
            " SELECT ".
                "q.QuoteID, ".
                "t.Pair, ".
                "t.TradeID, ".
                "q.TimeStart, ".
                "q.Time_T, ".
                "from_unixtime(q.`TimeStart`,'%Y')as DateYear, ".
                "q.TimeFrame, ".
                "q.SymbolCode, ".
                "q.O, ".
                "q.H, ".
                "q.L, ".
                "q.C ".
            " FROM ".
                "fa_quotes q ".
                "LEFT OUTER JOIN fa_trades t ON (q.TradeID = t.TradeID) ".
            " WHERE (1=1) " . $this->BuildWhere() .
            " ORDER BY ".
                "t.TradeID, ".
                "q.TimeStart ";
            //------------------------------------------------------------------
        }//sqls

        protected function BuildWhere() {
            $where = '';

            if( $this->_id ) {
                $where .= " AND (f.QuoteID=$this->_id) ";
            } else {
                if( $this->_trade ) $where .= " AND t.TradeId=$this->_trade ";
                if( $this->_start ) $where .= " AND q.TimeStart >= $this->_start" ;
                if( $this->_finish ) $where .= " AND q.TimeStart <= $this->_finish" ;
            }

            return $where;
        } //BuildWhere

    } //class QuoteDataItems
    //--------------------------------------------------------------------------------------------------
    class objForecastDataItems extends objAbstractDataItems {

            public $strong_interval = false;

        public function ClassName() {
            return  __CLASS__;
        }//ClassName

        public function getLast() {
            $max = count($this->_data);
            for($no = $max - 1; $no > -1; $no--) {
                $forecast = $this->_data[$no];
                if( 3==$forecast['Color'] ) return $forecast;
            }
            if( $max>0 ) return $this->_data[$max-1];
                else return false;
        } //getLastForecast

        public function isParamValid() {
            return !($this->_id || ( $this->_system && $this->_trade && ( $this->_start || $this->_finish ) ));
        } //isParamValid

        protected function BuildWhere() {
            $where = '';

            if( $this->_system ) $where .= " AND f.SystemID = $this->_system ";

            if( $this->_id ) {
                $where .= " AND (f.ForecastID=$this->_id) ";
            } else {
                if( $this->_trade ) $where .= " AND t.TradeId=$this->_trade ";
                if( $this->_start ) $where .= " AND f.BeginTime >= $this->_start" ;
                if( $this->_finish ) $where .= " AND f.BeginTime <= $this->_finish" ;
                if( $this->strong_interval ) {
                    if( $this->_start ) $where .= " AND COALESCE(f.EndTime, 3, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT)) >= $this->_start" ;
                    if( $this->_finish ) $where .= " AND COALESCE(f.EndTime, f.CloseTime, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT)) <= $this->_finish" ;
                } //if strong interval set
            }

            return $where;
        } //BuildWhere

        public function isExistActive() {
            for($i=0; $i<$this->Count(); $i++)    {
                if( $this->items[$i]->isActive()) return true;
            } //for
            return false;
        }//isExistActive

        //-------------------------------------------------------------------------------
        protected function CreateItem($aData) {
            $Item = new objForecastDataItem();
            $Item->Import($aData);
            return $Item;
        } //CreateItem
        //-------------------------------------------------------------------------------

        protected function _sqls() {
            //------------------------------------------------------------------
            $this->_sql_querys['items'] =
            "SELECT f.ForecastID, f.BeginPrice, f.BeginTime,f.EndPrice,f.EndTime, t.TradeID,t.Pair, f.Color, f.Side, t.Pipsize," .
                " f.StopPrice, ".
                " f.CloseTime is null AS flagActive, ".
                " (f.EndTime is Null) AS flagEndTime, ".
                " (f.EndPrice is Null) AS flagEndPrice, ".
                " (f.StopPrice is Null) AS flagStopPrice, ".

                " lq.LastCloseTime as LastTime, " .
                " lq.LastPrice as LastPrice, ".

                " COALESCE(f.CloseTime,lq.LastCloseTime) as CloseTime,   ".
                " COALESCE(f.ClosePrice,lq.LastClosePrice) as ClosePrice,   ".
                " COALESCE(f.EndTime, f.CloseTime, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT)) as EndTime, ".

                " round((1 - 2 * f.Side) * (COALESCE(f.ClosePrice, (1-f.Side)* r.Bid + f.Side*r.Ask, lq.LastClosePrice) - f.BeginPrice) / t.PipSize) as Pip, ".

                " COALESCE(round( (1 - 2 * f.Side) * (f.StopPrice - f.BeginPrice) / t.PipSize ), 0) as StopPip, ".
                " COALESCE(round( (1 - 2 * f.Side) * (f.EndPrice - f.BeginPrice) / t.PipSize ), 0) as EndPip, ".
                " COALESCE(round( (1 - 2 * f.Side) * (f.ClosePrice - f.BeginPrice) / t.PipSize ), 0) as ClosePip, ".

                " r.Ask, ".
                " r.Bid, ".
                " r.Time as RateTimeUnix, ".
                " r.Direction, ".
                " r.RateTime, ".
                " s.`Name` as `SystemName`, ".
                " s.ShortName as SystemShortName, ".
                " s.SystemID " .
            "FROM vfa_forecast f ".
                    " LEFT OUTER JOIN fa_trades t ON (f.TradeID = t.TradeID) ".
                    " LEFT OUTER JOIN fa_systems s ON (f.SystemID = s.SystemID) ".
                    " LEFT OUTER JOIN  ".
                        " (SELECT *, FROM_UNIXTIME(tr.`Time`, '%Y-%m-%d %H:%i:%s') as RateTime FROM fa_rates tr ) r ".
                        " ON (f.TradeID=r.TradeID) ".

                    " LEFT OUTER JOIN " .
                    " ( " .
                     " SELECT " .
                          " ttq.TradeID, " .
                          " ttq.C as LastClosePrice, " .
                          " GREATEST(ttq.O, ttq.C, ttq.H, ttq.L) as LastPrice, ".
                          " ttq.TimeStart as LastCloseTime, " .
                          " ttq.Time_T as LastCloseTimeT ".
                     " FROM fa_quotes ttq " .
                         " RIGHT OUTER JOIN ( " .
                               " SELECT tq.TradeID, max(tq.TimeStart) as max_quote_time " .
                               " FROM fa_quotes tq " .
                               " GROUP BY tq.TradeID) qq " .
                               " ON (qq.max_quote_time=ttq.TimeStart and qq.TradeID=ttq.TradeID) " .
                    ") lq " .
                    "ON (f.TradeID = lq.TradeID) "  .

            " WHERE (1=1) ". $this->BuildWhere() .

            " ORDER BY COALESCE(f.CloseTime,f.EndTime, GREATEST(f.BeginTime+s.ChartPeriod, lq.LastCloseTimeT))";

        }//_sqls

    } //class ForecastDataItems

//-------------------------------------------------------------------------------------------------------
?>
